package name.fuhan.biaoqing_fh;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import name.fuhan.biaoqiang_fh.R;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.GridLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;

import com.google.gson.Gson;
import com.viewpagerindicator.CirclePageIndicator;

public class BiaoQing_in extends RelativeLayout implements
		OnEditorActionListener, TextWatcher, View.OnClickListener {

	public BiaoQing_in(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public BiaoQing_in(Context context) {
		super(context);
	}

	protected String path = Config.path;
	int imageWidth;// 单个表情的宽
	int rowCount = Config.rowCount;// 每个GridLayout的行数和列数
	int columnCount = Config.columnCount;
	ArrayList<BiaoQing> data;// 储存所有表情的bitmap
	private CirclePageIndicator indicator;
	private ViewPager page;
	int maxTextCount = Config.maxTextCount;// 输入框的最大字数
	private TextView textView;
	boolean EnterIsSend = Config.EnterIsSend;
	int lines = Config.lines;
	int maxlines = Config.maxlines;
	Class showUsersActivity = Config.showUsersActivity;
	Class showUserActivity = Config.showUserActivity;
	int requestCode = Config.requestCode;
	String showNameKey = Config.showNameKey;

	static class BiaoQing {
		Bitmap bitmap;
		String name;
	}

	public static class Config {
		static Config config = new Config();
		static String path;

		static int lines = 5;
		static int maxlines = 20;

		static int rowCount = 3;// 每个GridLayout的行数和列数
		static int columnCount = 7;

		static int maxTextCount = 140;// 输入框的最大字数

		static boolean EnterIsSend;// 回车变成发送

		static Class showUsersActivity ;// 点击@键时弹出的activity
		static Class showUserActivity ;// 点击@键时弹出的activity
		static String showNameKey = "name";// intent中用于显示在编辑框中的名字的key

		static int requestCode = 123;// 启动showUserActivity的返回码

		public static <T extends Activity> Config setShowUsersActivity(
				Class<T> cls, int requestCode) {
			showUsersActivity = cls;
			Config.requestCode = requestCode;
			return config;
		}

		/**
		 * 启动被@的用户的个人详情页时需要的参数
		 * 
		 * @param cls
		 *            Activity的class
		 * @param showNameKey
		 *            intent中用于显示在编辑框中的名字的key,对应的值必须为String
		 * @return
		 */
		public static <T extends Activity> Config setShowUserActivity(
				Class<T> cls, String showNameKey) {
			showUserActivity = cls;
			Config.showNameKey = showNameKey;
			return config;
		}

		public static Config setEnterIsSend(boolean enterIsSend) {
			EnterIsSend = enterIsSend;
			return config;
		}

		/**
		 * 设置输入框的高度为几行,EnterIsSend为true时无效
		 * 
		 * @param lines
		 *            默认为5行
		 */
		public static Config setLines(int lines) {
			Config.lines = lines;
			return config;
		}

		/**
		 * 设置输入框的最多可输入几行,EnterIsSend为true时无效
		 * 
		 * @param maxlines
		 *            默认为20行
		 */
		public static Config setMaxLines(int maxlines) {
			Config.maxlines = maxlines;
			return config;
		}

		/**
		 * 设置自定义表情符的目录
		 * 
		 * @param path
		 *            assets下的文件夹名
		 * @return {@link BiaoQing_in.Config}
		 */
		public static Config setPath(String path) {
			Config.path = path;
			return config;
		}

		public static Config setRowCountAndColumnCount(int rowCount,
				int columnCount) {
			Config.rowCount = rowCount;
			Config.columnCount = columnCount;

			return config;
		}

		public static Config setMaxTextCount(int maxTextCount) {
			Config.maxTextCount = maxTextCount;
			return config;
		}

	}

	Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case 1:
				data = (ArrayList<BiaoQing>) msg.obj;
				adapter.notifyDataSetChanged();
				break;

			default:
				break;
			}
		}
	};
	MyPageAdapter adapter = new MyPageAdapter();
	private View imageView1;
	private View imageView2;
	private View llView;
	private EditText editText;
	private View send1;
	private View send2;

	private synchronized void init(Context context) {
		// 去读取
		new Thread(new Runnable() {
			public void run() {
				if (!TextUtils.isEmpty(path)) {
					try {
						String[] list = getContext().getApplicationContext()
								.getAssets().list(path);
						if (list == null || list.length == 0) {
							throw new RuntimeException("未在assets/" + path
									+ "文件夹下发现图片文件");
						}
						ArrayList<BiaoQing> data = new ArrayList<BiaoQing>(
								list.length);
						for (String fileName : list) {
							Bitmap bitmap = decodeSampledBitmapFromResource(
									getContext().getApplicationContext()
											.getAssets()
											.open(path + "/" + fileName),
									imageWidth, imageWidth);
							BiaoQing biaoQing = new BiaoQing();
							biaoQing.bitmap = bitmap;
							biaoQing.name = fileName;
							data.add(biaoQing);
						}
						synchronized (BiaoQing_in.this) {
							handler.sendMessage(handler.obtainMessage(1, data));
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				} else {
					throw new RuntimeException("请指定在assets下存放表情文件的目录");
				}
			}
		}).start();

		View inflate = LayoutInflater.from(context).inflate(R.layout.shuru,
				null);
		addView(inflate);
		page = $(R.id.pager);
		indicator = $(R.id.indicator);
		page.setAdapter(adapter);
		indicator.setViewPager(page);
		editText = $(R.id.editText1);
		editText.addTextChangedListener(this);// 监听文字改变
		editText.setOnClickListener(this);
		editText.setLines(lines);
		editText.setMaxLines(maxlines);
		textView = $(R.id.textView1);
		textView.setText("0/" + maxTextCount);
		llView = $(R.id.linearLayout2);
		imageView1 = $(R.id.imageView1);
		imageView1.setOnClickListener(this);
		((Activity) getContext()).getWindow().setSoftInputMode(
				WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
						| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

		imageView2 = $(R.id.imageView2);
		imageView2.setOnClickListener(this);

		Class showUserActivity;

		send1 = $(R.id.btn_send1);
		send2 = $(R.id.btn_send2);
		if (EnterIsSend) {// 如果是单行输入
			editText.setImeOptions(EditorInfo.IME_ACTION_SEND);
			editText.setInputType(EditorInfo.TYPE_CLASS_TEXT);
			editText.setOnEditorActionListener(this);// 监听发送键
			send1.setVisibility(View.VISIBLE);
			send2.setVisibility(View.GONE);
		} else {
			send1.setVisibility(View.GONE);
			send2.setVisibility(View.VISIBLE);
		}
		send1.setOnClickListener(this);
		send2.setOnClickListener(this);

	}

	public interface OnSendClickListener {
		public void onSend(String editable);
	}

	public void setOnSendClickListener(OnSendClickListener sendListener) {
		this.sendListener = sendListener;
	}

	OnSendClickListener sendListener;

	@Override
	protected void onAttachedToWindow() {
		super.onAttachedToWindow();
		init(getContext());
	}

	class MyPageAdapter extends PagerAdapter {

		@Override
		public int getCount() {
			int count;
			if (data != null) {
				count = (data.size() % (rowCount * columnCount) == 0) ? (data
						.size() / (rowCount * columnCount)) : (data.size()
						/ (rowCount * columnCount) + 1);
			} else {
				count = 0;
			}
			return count;
		}

		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			LinearLayout ll = (LinearLayout) View.inflate(getContext(),
					R.layout.item, null);
			GridLayout gl = (GridLayout) ll.findViewById(R.id.gl);
			gl.setRowCount(rowCount);
			gl.setColumnCount(columnCount);
			int count = rowCount * columnCount;
			for (int i = 0; i < (position == getCount() - 1 ? data.size()
					% count : count); i++) {
				BiaoQing biaoQing = data.get(count * position + i);
				ImageView imageView = new ImageView(getContext());
				android.view.ViewGroup.LayoutParams params = new LayoutParams(
						imageWidth, imageWidth);
				imageView.setLayoutParams(params);
				imageView.setTag(biaoQing.name);
				imageView.setOnClickListener(biaoQingClickListener);
				imageView.setImageBitmap(biaoQing.bitmap);
				gl.addView(imageView);
			}
			container.addView(ll);
			return ll;
		}

		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			container.removeView((View) object);
		}

		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {
			return arg0 == arg1;
		}

	}

	OnBiaoQingClickListener biaoQingClickListener = new OnBiaoQingClickListener();

	class OnBiaoQingClickListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			String name = (String) v.getTag();
			SpannableString text = new SpannableString("&[" + name + "]");
			Bitmap bitmap = null;
			for (BiaoQing b : data) {
				if (b.name.equals(name)) {
					bitmap = b.bitmap;
					break;
				}
			}
			int lineHeight = editText.getLineHeight();
			bitmap = Bitmap.createScaledBitmap(bitmap, lineHeight, lineHeight,
					true);
			text.setSpan(new ImageSpan(getContext(), bitmap), 0,
					name.length() + 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
			editText.getText().insert(editText.getSelectionStart(), text);

		}
	}

	ArrayList<Map<String, Object>> atList = new ArrayList<Map<String,Object>>();
	
	/**
	 * 接受来自用户选择器的数据并添加到编辑框中
	 */
	public void appendAtName(Intent data) {
		try {
			Bundle bundle = data.getExtras();
			Map<String, Object> map = new HashMap<String, Object>();
			Set<String> keySet = bundle.keySet();
			Iterator<String> iterator = keySet.iterator();
			while (iterator.hasNext()) {
				String k = iterator.next();
				Object v = bundle.get(k);
				map.put(k, v);
			}
			
			atList.add( map);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		String showName = data.getStringExtra(showNameKey);
		SpannableStringBuilder spanText = new SpannableStringBuilder("@"
				+ showName + " ");
		spanText.setSpan(new MyURLSpan(data,getContext(),showUserActivity), 0, showName.length() + 2,
				Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
		editText.setMovementMethod(LinkMovementMethod.getInstance());
		editText.append(spanText);
	}

	public static class MyURLSpan extends android.text.style.ClickableSpan {

		Intent data;
		Context context;
		Class showUserActivity;

		MyURLSpan(Intent data,Context context,Class showUserActivity) {
			this.data = data;
			this.context = context;
			this.showUserActivity = showUserActivity;
		}

		/**
		 * 处理@用户的点击事件的
		 */
		@Override
		public void onClick(View widget) {
			// Toast.makeText(getContext(), userId+","+value, 0).show();
			data.setClass(context, showUserActivity);
			context.startActivity(data);
		}
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		measureChildren(widthMeasureSpec, heightMeasureSpec);
		int width = getMeasuredWidth();
		imageWidth = width / columnCount;
		android.view.ViewGroup.LayoutParams layoutParams = llView
				.getLayoutParams();
		layoutParams.height = imageWidth * rowCount + 15;
		llView.setLayoutParams(layoutParams);
	}

	public <T extends View> T $(int id) {
		return (T) findViewById(id);
	}

	public static int calculateInSampleSize(BitmapFactory.Options options,
			int reqWidth, int reqHeight) {
		// 源图片的高度和宽度
		final int height = options.outHeight;
		final int width = options.outWidth;
		int inSampleSize = 1;
		if (height > reqHeight || width > reqWidth) {
			// 计算出实际宽高和目标宽高的比率
			final int heightRatio = Math.round((float) height
					/ (float) reqHeight);
			final int widthRatio = Math.round((float) width / (float) reqWidth);
			// 选择宽和高中最小的比率作为inSampleSize的值，这样可以保证最终图片的宽和高
			// 一定都会大于等于目标的宽和高。
			inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
		}
		return inSampleSize;
	}

	public static Bitmap decodeSampledBitmapFromResource(
			InputStream fileInputStream, int reqWidth, int reqHeight) {
		// 第一次解析将inJustDecodeBounds设置为true，只获取图片宽,高大小
		final BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true; // 不会加载整个图片文件
		BitmapFactory.decodeStream(fileInputStream, null, options);
		// 调用上面定义的方法计算inSampleSize值
		options.inSampleSize = calculateInSampleSize(options, reqWidth,
				reqHeight);
		// 使用获取到的inSampleSize值再次解析图片
		options.inJustDecodeBounds = false; // 会根据inSampleSize加载图片的部分数据到内存
		return BitmapFactory.decodeStream(fileInputStream, null, options);
	}

	@Override
	public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {// 处理send按钮
		if (actionId == EditorInfo.IME_ACTION_SEND) {
			GoGoGo(editText.getText());
			return true;
		}

		return false;
	}

	@Override
	public void beforeTextChanged(CharSequence s, int start, int count,
			int after) {
		flag = false;
		Log.e("TGABQ", "beforeTextChanged()"+"s="+s+"start="+start+"count="+count+"after="+after);
		if (count>1) {
			return;
		}
		if (count>0) {//当变化为删除的时候
			//start删除时光标的位置
			String text = s.toString();
			int atStart = text.lastIndexOf("@",start);
			if (atStart==-1) {
				return;
			}
			int atEnd = text.indexOf(" ",atStart);
			if (atEnd==-1) {
				Toast.makeText(getContext(), "atEnd==-1", 0).show();
			}
			if (start>=atStart&&start<=atEnd) {
//				editText.getText().delete(atStart, atEnd-1);
				flag = true;
				this.atStart = atStart;
				this.atEnd = atEnd;
				index = 0;
				while((atStart=text.lastIndexOf("@",atStart-1))!=-1){
					index++;
				}
				return ;
			}
			
		}
	}
	int index ;
boolean flag;
int atStart;
int atEnd;

	@Override
	public void onTextChanged(CharSequence s, int start, int before, int count) {
		if (flag) {
			Log.e("TGABQ", "delete()"+editText.getText()+"("+atStart+","+atEnd+")");
			editText.getText().delete(atStart, atEnd);
			atList.remove(index);
		}
	}

	@Override
	public void afterTextChanged(Editable s) {
		int length = s.length();
		String string = s.toString();
		int jieshu = 0;
		int biaoqingquanchang = 0;
		while (true) {
			int kaishi = string.indexOf("&[", jieshu);
			if (kaishi == -1) {
				break;
			}
			jieshu = string.indexOf("]", kaishi);
			length -= (jieshu - kaishi);
			biaoqingquanchang += (jieshu - kaishi);
		}

		if (length >= maxTextCount) {
			if (string.lastIndexOf("]") == s.length() - 1) {
				s.delete(string.lastIndexOf("&["), s.length());
			} else {
				s.delete(maxTextCount + biaoqingquanchang, s.length());
			}
		}
		textView.setText((length > maxTextCount ? maxTextCount : length) + "/"
				+ maxTextCount);
	}

	@Override
	public void onClick(View v) {
		if (v == imageView1) {
			llView.setVisibility(llView.getVisibility() == View.GONE ? View.VISIBLE
					: View.GONE);
			if (llView.getVisibility() == View.VISIBLE) {
				((InputMethodManager) getContext().getSystemService(
						Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(
						editText.getWindowToken(),
						InputMethodManager.HIDE_NOT_ALWAYS);
			} else {
				((InputMethodManager) getContext().getSystemService(
						Context.INPUT_METHOD_SERVICE)).showSoftInput(editText,
						InputMethodManager.SHOW_IMPLICIT);
				// ((Activity)getContext()).getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
			}
		} else if (v == imageView2) {
			Intent intent = new Intent(getContext(), showUsersActivity);
			((Activity) getContext()).startActivityForResult(intent,
					requestCode);

		} else if (v == editText) {
			llView.setVisibility(View.GONE);
		} else if (v == send1 || v == send2) {
			GoGoGo(editText.getText());
		}
	}

	private void GoGoGo(Editable editable) {
		String json = new Gson().toJson(atList);
		try {
			sendListener.onSend(editable+"AT*"+json);
		} catch (NullPointerException e) {
			throw new RuntimeException("您必须指定接受发送事件的监听");
		}
	}

}
